#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

#include "tabvar.h"

#define NB_VAR 20

struct variable{
  char * nom;
  char * type;
  double valeur;
  char * adresse;
};

typedef struct variable * variable;

static variable tabV[NB_VAR];
static int taille_tabV = 0;

/**************************************/
extern char * chaine_dup(char * s){
  int taille = strlen(s);
  char * t = malloc((taille+1) * sizeof(*t));
  int i;
  for(i=0; i<taille; i++)
    t[i]=s[i];
  t[taille]='\0';
  return t;
}
/**************************************/

static void ajouterVar(char * nom, char * type, double valeur){
  variable var = malloc(sizeof(struct variable));
  assert(var);
  var->nom = chaine_dup(nom);
  var->type = type;
  var->valeur = valeur;
  var->adresse = NULL;

  tabV[taille_tabV++] = var;
}

static int rechercherVar(char * nom){
  int i;
  for(i=0; i < taille_tabV; i++)
    if(strcmp(nom, tabV[i]->nom) == 0)
      return i;
  return -1;
}

static void modifierVar(char * nom, double valeur){
  int pos = rechercherVar(nom);
  assert(pos > -1);
  tabV[pos]->valeur = valeur;
}

/**************************************/

extern void tabvar_declarer(char * nom, char * type, double valeur){
  ajouterVar(nom, type, valeur);
  //printf("declaration de [%s] \n", nom);
}

extern void tabvar_affecter(char * nom, double valeur){
  int pos = rechercherVar(nom);
  if(pos > -1){
    modifierVar(nom, valeur);
    //printf("modification de [%s] \n", nom);
  }
  else{
    fprintf(stderr, "\nVariable non declare: [%s] \n", nom);
    exit(0);
  }
}

extern void tabvar_affecter_adresse(char * nom, char * adresse){
  int pos = rechercherVar(nom);
  if(pos > -1){
    tabV[pos]->adresse = chaine_dup(adresse);
  }
  else{
    fprintf(stderr, "\nVariable non declare: [%s] \n", nom);
    exit(0);
  }
}

extern double tabvar_recuperer(char *nom){
  int pos = rechercherVar(nom);
  if(pos < 0){
    fprintf(stderr, "\nVariable non defini: [%s] \n", nom);
    exit(0);
  }
  else
    if(strcmp(tabV[pos]->type, "pointeur") == 0)
      return tabvar_recuperer(tabV[pos]->adresse);
    else
      return tabV[pos]->valeur;

  return 0;
}

extern char * tabvar_recuperer_type(char *nom){
  int pos = rechercherVar(nom);
  if(pos < 0){
    fprintf(stderr, "\nVariable non defini: [%s] \n", nom);
    exit(0);
  }
  else
    return tabV[pos]->type;
  return 0;
}

extern char * tabvar_recuperer_adresse(char *nom){
  int pos = rechercherVar(nom);
  if(pos < 0){
    fprintf(stderr, "\nVariable non defini: [%s] \n", nom);
    exit(0);
  }
  else
    return tabV[pos]->adresse;

  return 0;
}

extern void tabvar_afficher(){
  int i;
  for(i=0; i < taille_tabV; i++)
    printf("Identificateur: %s\tType:%s\tValeur: %f\n", tabV[i]->nom, tabV[i]->type, tabvar_recuperer(tabV[i]->nom));
}
